package com.rtf.framework.monitor.export.jvm;

import com.rtf.framework.monitor.config.AppMonitorProperties;
import com.google.common.collect.Lists;
import io.prometheus.client.Collector;
import io.prometheus.client.CounterMetricFamily;
import io.prometheus.client.GaugeMetricFamily;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;

/**
 * Exports metrics about JVM classloading.
 * <p>
 * Example usage:
 * <pre>
 * {@code
 *   new ClassLoadingExports().register();
 * }
 * </pre>
 * Example metrics being exported:
 * <pre>
 *   jvm_classes_loaded{} 1000
 *   jvm_classes_loaded_total{} 2000
 *   jvm_classes_unloaded_total{} 500
 * </pre>
 */
public class AppClassLoadingExports extends Collector {
  private final ClassLoadingMXBean clBean;

  public AppClassLoadingExports() {
    this(ManagementFactory.getClassLoadingMXBean());
  }

  public AppClassLoadingExports(ClassLoadingMXBean clBean) {
    this.clBean = clBean;
  }

  void addClassLoadingMetrics(List<MetricFamilySamples> sampleFamilies) {
    List<String> labels = Lists.newArrayList("appName") ;

    GaugeMetricFamily jvm_classes_loaded = new GaugeMetricFamily(
            "jvm_classes_loaded",
            "The number of classes that are currently loaded in the JVM",
            labels ) ;
    jvm_classes_loaded.addMetric( Lists.newArrayList(AppMonitorProperties.getAppName()) , clBean.getLoadedClassCount() ) ;
    sampleFamilies.add( jvm_classes_loaded );

    CounterMetricFamily jvm_classes_loaded_total = new CounterMetricFamily(
            "jvm_classes_loaded_total",
            "The total number of classes that have been loaded since the JVM has started execution",
            labels) ;
    jvm_classes_loaded_total.addMetric( Lists.newArrayList(AppMonitorProperties.getAppName()) , clBean.getTotalLoadedClassCount() ) ;
    sampleFamilies.add(jvm_classes_loaded_total);

    CounterMetricFamily jvm_classes_unloaded_total = new CounterMetricFamily(
            "jvm_classes_unloaded_total",
            "The total number of classes that have been unloaded since the JVM has started execution",
            labels ) ;
    jvm_classes_unloaded_total.addMetric( Lists.newArrayList(AppMonitorProperties.getAppName()) , clBean.getUnloadedClassCount() ) ;
    sampleFamilies.add( jvm_classes_unloaded_total );
  }

  @Override
  public List<MetricFamilySamples> collect() {
    List<MetricFamilySamples> mfs = new ArrayList<MetricFamilySamples>();
    addClassLoadingMetrics(mfs);
    return mfs;
  }
}
